﻿using System;
using System.Collections.Generic;
using System.Linq;
using cludg.Domain.Environment;
using cludg.Repository.Environment;
using cludg.Repository.Security;
using cludg.Repository.Transactions;
using cludg.Infrastructure.Core.Attributes;

namespace cludg.Services.Environment
{
	public class HistoryService : IHistoryService
	{
		[Dependency]
		public ITransactionFactory TransactionFactory { get; set; }

		[Dependency]
		public IHistoryRepository Repository { get; set; }

		[Dependency]
		public ISecurityRepository SecurityRepository { get; set; }

		// TODO: Нужно чистить список, когда закрывается сессия
		private readonly Dictionary<string, List<string>> _viewHistory = new Dictionary<string, List<string>>();

		public IQueryable<HistoryEntry> All
		{
			get { return Repository.Get(); }
		}

		public void Add(string objectId, HistoryEntryType type, string userId, string sessionId)
		{
			// если в рамках одной сессии уже объект уже просматривали - не добавляем запись
			if (type == HistoryEntryType.View)
			{
				if (CheckIsAlreadyViewed(objectId, sessionId, userId))
				{
					return;
				}
			}

			using (var tran = TransactionFactory.BeginTransaction())
			{
				Repository.Add(new HistoryEntry
				{
					ObjectId = objectId,
					Type = type,
					Date = DateTime.Now,
					User = string.IsNullOrWhiteSpace(userId) ? null : SecurityRepository.GetUserById(userId)
				});
				tran.Commit();
			}
		}

		private bool CheckIsAlreadyViewed(string objectId, string sessionId, string userId)
		{
			var entryId = sessionId + userId;

			if (_viewHistory.ContainsKey(entryId))
			{
				var alreadyViewed = _viewHistory[entryId].Contains(objectId);
				if (!alreadyViewed)
				{
					_viewHistory[entryId].Add(objectId);
				}
				return alreadyViewed;
			}

			_viewHistory.Add(entryId, new List<string> { objectId });
			return false;
		}
	}
}
